home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / mapmem.zip / DRIVER / MAPMEM.C < prev    next >
C/C++ Source or Header  |  1993-02-24  |  14KB  |  527 lines

  1. //
  2. // Simple driver that demonstrates mapping physical memory into
  3. //   a user mode process's address space
  4. //
  5.  
  6. #include "ntddk.h"
  7. #include "..\mapmem.h"
  8. #include "stdarg.h"
  9.  
  10.  
  11.  
  12. //
  13. // The following was not included in the October release of the
  14. //   preliminary NT DDK, and is necessary when utilizing the
  15. //   ZwMapViewOfSection API.
  16. //
  17.  
  18. #define SECTION_QUERY       0x0001
  19. #define SECTION_MAP_WRITE   0x0002
  20. #define SECTION_MAP_READ    0x0004
  21. #define SECTION_MAP_EXECUTE 0x0008
  22. #define SECTION_EXTEND_SIZE 0x0010
  23.  
  24. #define SECTION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY | \
  25.                             SECTION_MAP_WRITE                      | \
  26.                             SECTION_MAP_READ                       | \
  27.                             SECTION_MAP_EXECUTE                    | \
  28.                             SECTION_EXTEND_SIZE)
  29.  
  30. typedef enum _SECTION_INHERIT {
  31.     ViewShare = 1,
  32.     ViewUnmap = 2
  33. } SECTION_INHERIT;
  34.  
  35. #define PAGE_NOACCESS          0x01     // winnt
  36. #define PAGE_READONLY          0x02     // winnt
  37. #define PAGE_READWRITE         0x04     // winnt
  38. #define PAGE_WRITECOPY         0x08
  39. #define PAGE_EXECUTE           0x10
  40. #define PAGE_EXECUTE_READ      0x20
  41. #define PAGE_EXECUTE_READWRITE 0x40
  42. #define PAGE_EXECUTE_WRITECOPY 0x80
  43. #define PAGE_GUARD            0x100
  44. #define PAGE_NOCACHE          0x200
  45.  
  46. NTSTATUS
  47. ZwMapViewOfSection(
  48.     IN HANDLE SectionHandle,
  49.     IN HANDLE ProcessHandle,
  50.     IN OUT PVOID *BaseAddress,
  51.     IN ULONG ZeroBits,
  52.     IN ULONG CommitSize,
  53.     IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
  54.     IN OUT PULONG ViewSize,
  55.     IN SECTION_INHERIT InheritDisposition,
  56.     IN ULONG AllocationType,
  57.     IN ULONG Protect
  58.     );
  59.  
  60.  
  61. //
  62. // Function prototypes for this module
  63. //
  64.  
  65. NTSTATUS
  66. MapMemCreateClose(
  67.     IN PDEVICE_OBJECT DeviceObject,
  68.     IN PIRP Irp
  69.     );
  70.  
  71. NTSTATUS
  72. MapMemDispatch(
  73.     IN PDEVICE_OBJECT DeviceObject,
  74.     IN PIRP Irp
  75.     );
  76.  
  77. NTSTATUS
  78. MapMemMapTheMemory(
  79.     IN PDEVICE_OBJECT DeviceObject,
  80.     IN OUT PVOID      ioBuffer,
  81.     IN ULONG          inputBufferLength,
  82.     IN ULONG          outputBufferLength
  83.     );
  84.  
  85. #if DBG
  86. #define MapMemDebugPrint(arg) DbgPrint arg
  87. #else
  88. #define MapMemDebugPrint(arg)
  89. #endif
  90.  
  91.  
  92.  
  93. //
  94. // The code...
  95. //
  96.  
  97. NTSTATUS
  98. DriverEntry(
  99.     IN PDRIVER_OBJECT DriverObject,
  100.     IN PUNICODE_STRING RegistryPath
  101.     )
  102. {
  103.  
  104.     PDEVICE_OBJECT deviceObject = NULL;
  105.     NTSTATUS       ntStatus;
  106.     WCHAR          deviceNameBuffer[] = L"\\Device\\MapMem";
  107.     UNICODE_STRING deviceNameUnicodeString;
  108.  
  109.  
  110.     MapMemDebugPrint(("MapMem: entering DriverEntry\n"));
  111.  
  112.  
  113.     RtlInitUnicodeString(&deviceNameUnicodeString,
  114.                          deviceNameBuffer);
  115.  
  116.     //
  117.     // Create the device object
  118.     //
  119.  
  120.     ntStatus = IoCreateDevice(
  121.                  DriverObject,
  122.                  0,
  123.                  &deviceNameUnicodeString,
  124.                  FILE_DEVICE_UNKNOWN,
  125.                  0,
  126.                  TRUE,
  127.                  &deviceObject
  128.                  );
  129.  
  130.  
  131.     if (NT_SUCCESS(ntStatus))
  132.     {
  133.         //
  134.         // Create dispatch points for device control, create, close.
  135.         //
  136.  
  137.         DriverObject->MajorFunction[IRP_MJ_CREATE]         =
  138.         DriverObject->MajorFunction[IRP_MJ_CLOSE]          = MapMemCreateClose;
  139.         DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MapMemDispatch;
  140.     }
  141.  
  142.     return ntStatus;
  143. }
  144.  
  145.  
  146.  
  147. NTSTATUS
  148. MapMemCreateClose(
  149.     IN PDEVICE_OBJECT DeviceObject,
  150.     IN PIRP Irp
  151.     )
  152. {
  153.     //
  154.     // No need to do anything.
  155.     //
  156.  
  157.     //
  158.     // Fill these in before calling IoCompleteRequest.
  159.     //
  160.     // DON'T get cute and try to use the status field of
  161.     // the irp in the return status.  That IRP IS GONE as
  162.     // soon as you call IoCompleteRequest.
  163.     //
  164.  
  165.     MapMemDebugPrint(("MapMemOpenClose: enter\n"));
  166.  
  167.     Irp->IoStatus.Status = STATUS_SUCCESS;
  168.     Irp->IoStatus.Information = 0;
  169.  
  170.     IoCompleteRequest(
  171.         Irp,
  172.         IO_NO_INCREMENT
  173.         );
  174.  
  175.     return STATUS_SUCCESS;
  176.  
  177. }
  178.  
  179.  
  180.  
  181. NTSTATUS
  182. MapMemDispatch(
  183.     IN PDEVICE_OBJECT DeviceObject,
  184.     IN PIRP Irp
  185.     )
  186. {
  187.     PIO_STACK_LOCATION irpStack;
  188.     PVOID              ioBuffer;
  189.     ULONG              inputBufferLength;
  190.     ULONG              outputBufferLength;
  191.     ULONG              ioControlCode;
  192.     NTSTATUS           ntStatus;
  193.  
  194.     //
  195.     // Init to default settings- we only expect 1 type of
  196.     //     IOCTL to roll through here, all others an error.
  197.     //
  198.  
  199.     Irp->IoStatus.Status      = STATUS_INVALID_PARAMETER;
  200.     Irp->IoStatus.Information = 0;
  201.  
  202.  
  203.     //
  204.     // Get a pointer to the current location in the Irp. This is where
  205.     //     the function codes and parameters are located.
  206.     //
  207.  
  208.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  209.  
  210.  
  211.     //
  212.     // Get the pointer to the input/output buffer and it's length
  213.     //
  214.  
  215.     ioBuffer = Irp->AssociatedIrp.SystemBuffer;
  216.     inputBufferLength =
  217.         irpStack->Parameters.DeviceIoControl.InputBufferLength;
  218.     outputBufferLength =
  219.         irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  220.  
  221.  
  222.     switch (irpStack->MajorFunction)
  223.     {
  224.  
  225.     case IRP_MJ_DEVICE_CONTROL:
  226.  
  227.         ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  228.  
  229.         switch (ioControlCode)
  230.         {
  231.         case IOCTL_MAPMEM_MAP_USER_PHYSICAL_MEMORY:
  232.  
  233.             Irp->IoStatus.Status = MapMemMapTheMemory (DeviceObject,
  234.                                                        ioBuffer,
  235.                                                        inputBufferLength,
  236.                                                        outputBufferLength
  237.                                                        );
  238.  
  239.             if (NT_SUCCESS(Irp->IoStatus.Status))
  240.             {
  241.                 //
  242.                 // Success! Set the following to sizeof(PVOID) to
  243.                 //     indicate we're passing valid data back.
  244.                 //
  245.  
  246.                 Irp->IoStatus.Information = sizeof(PVOID);
  247.  
  248.                 MapMemDebugPrint(("MapMem: memory successfully mapped :)\n"));
  249.             }
  250.  
  251.             else
  252.  
  253.                 MapMemDebugPrint(("MapMem: memory map failed :(\n"));
  254.  
  255.             break;
  256.  
  257.         default:
  258.  
  259.             MapMemDebugPrint(("MapMem: unknown IRP_MJ_DEVICE_CONTROL\n"));
  260.  
  261.  
  262.             break;
  263.  
  264.         } // switch (ioControlCode)
  265.  
  266.         break;
  267.     }
  268.  
  269.  
  270.     //
  271.     // DON'T get cute and try to use the status field of
  272.     // the irp in the return status.  That IRP IS GONE as
  273.     // soon as you call IoCompleteRequest.
  274.     //
  275.  
  276.     ntStatus = Irp->IoStatus.Status;
  277.  
  278.     IoCompleteRequest(Irp,
  279.                       IO_NO_INCREMENT);
  280.  
  281.  
  282.     //
  283.     // We never have pending operation so always return the status code.
  284.     //
  285.  
  286.     return ntStatus;
  287. }
  288.  
  289.  
  290.  
  291. NTSTATUS
  292. MapMemMapTheMemory(
  293.     IN PDEVICE_OBJECT DeviceObject,
  294.     IN OUT PVOID      ioBuffer,
  295.     IN ULONG          inputBufferLength,
  296.     IN ULONG          outputBufferLength
  297.     )
  298. {
  299.     PPHYSICAL_MEMORY_INFO ppmi = (PPHYSICAL_MEMORY_INFO) ioBuffer;
  300.  
  301.     INTERFACE_TYPE     interfaceType;
  302.     ULONG              busNumber;
  303.     PHYSICAL_ADDRESS   physicalAddress;
  304.     ULONG              length;
  305.     UNICODE_STRING     physicalMemoryUnicodeString;
  306.     OBJECT_ATTRIBUTES  objectAttributes;
  307.     HANDLE             physicalMemoryHandle  = NULL;
  308.     PVOID              PhysicalMemorySection = NULL;
  309.     ULONG              inIoSpace, inIoSpace2;
  310.     NTSTATUS           ntStatus;
  311.     PHYSICAL_ADDRESS   physicalAddressBase;
  312.     PHYSICAL_ADDRESS   physicalAddressEnd;
  313.     PHYSICAL_ADDRESS   viewBase;
  314.     PHYSICAL_ADDRESS   mappedLength;
  315.     BOOLEAN            translateBaseAddress;
  316.     BOOLEAN            translateEndAddress;
  317.     PVOID              virtualAddress;
  318.  
  319.  
  320.  
  321.     if ( ( inputBufferLength  < sizeof (PHYSICAL_MEMORY_INFO) ) ||
  322.          ( outputBufferLength < sizeof (PVOID) ) )
  323.     {
  324.        MapMemDebugPrint(("MapMem: Insufficient input or output buffer\n"));
  325.  
  326.        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  327.  
  328.        goto done;
  329.     }
  330.  
  331.     interfaceType   = ppmi->interfaceType;
  332.     busNumber       = ppmi->busNumber;
  333.     physicalAddress = ppmi->physicalAddress;
  334.     length          = ppmi->length;
  335.  
  336.  
  337.     //
  338.     // Get a pointer to physical memory...
  339.     //
  340.     // - Create the name
  341.     // - Initialize the data to find the object
  342.     // - Open a handle to the oject and check the status
  343.     // - Get a pointer to the object
  344.     // - Free the handle
  345.     //
  346.  
  347.     RtlInitUnicodeString(&physicalMemoryUnicodeString,
  348.                          L"\\Device\\PhysicalMemory");
  349.  
  350.     InitializeObjectAttributes (&objectAttributes,
  351.                                 &physicalMemoryUnicodeString,
  352.                                 OBJ_CASE_INSENSITIVE,
  353.                                 (HANDLE) NULL,
  354.                                 (PSECURITY_DESCRIPTOR) NULL);
  355.  
  356.     ntStatus = ZwOpenSection (&physicalMemoryHandle,
  357.                               SECTION_ALL_ACCESS,
  358.                               &objectAttributes);
  359.  
  360.     if (!NT_SUCCESS(ntStatus))
  361.     {
  362.         MapMemDebugPrint(("MapMem: ZwOpenSection failed\n"));
  363.  
  364.         goto done;
  365.     }
  366.  
  367.     ntStatus = ObReferenceObjectByHandle (physicalMemoryHandle,
  368.                                           SECTION_ALL_ACCESS,
  369.                                           (POBJECT_TYPE) NULL,
  370.                                           KernelMode,
  371.                                           &PhysicalMemorySection,
  372.                                           (POBJECT_HANDLE_INFORMATION) NULL);
  373.  
  374.     if (!NT_SUCCESS(ntStatus))
  375.     {
  376.         MapMemDebugPrint(("MapMem: ObReferenceObjectByHandle failed\n"));
  377.  
  378.         goto close_handle;
  379.     }
  380.  
  381.     //
  382.     // Have a second variable used for the second HalTranslateBusAddres call.
  383.     //
  384.  
  385.     inIoSpace = inIoSpace2 = 0;
  386.  
  387.  
  388.     //
  389.     // Initialize the physical addresses that will be translated
  390.     //
  391.  
  392.     physicalAddressEnd = RtlLargeIntegerAdd (physicalAddress,
  393.                                              RtlConvertUlongToLargeInteger(
  394.                                                  length));
  395.  
  396.     //
  397.     // Translate the physical addresses.
  398.     //
  399.  
  400.     translateBaseAddress =
  401.         HalTranslateBusAddress (interfaceType,
  402.                                 busNumber,
  403.                                 physicalAddress,
  404.                                 &inIoSpace,
  405.                                 &physicalAddressBase);
  406.  
  407.     translateEndAddress =
  408.         HalTranslateBusAddress (interfaceType,
  409.                                 busNumber,
  410.                                 physicalAddressEnd,
  411.                                 &inIoSpace2,
  412.                                 &physicalAddressEnd);
  413.  
  414.     if ( !(translateBaseAddress && translateEndAddress) )
  415.     {
  416.         MapMemDebugPrint(("MapMem: HalTranslateBusAddress failed\n"));
  417.  
  418.         ntStatus = STATUS_UNSUCCESSFUL;
  419.  
  420.         goto close_handle;
  421.     }
  422.  
  423.     //
  424.     // Calculate the length of the memory to be mapped
  425.     //
  426.  
  427.     mappedLength = RtlLargeIntegerSubtract (physicalAddressEnd,
  428.                                             physicalAddressBase);
  429.  
  430.  
  431.     //
  432.     // If the mappedlength is zero, somthing very weird happened in the HAL
  433.     // since the Length was checked against zero.
  434.     //
  435.  
  436.     if (mappedLength.LowPart == 0)
  437.     {
  438.         MapMemDebugPrint(("MapMem: mappedLength.LowPart == 0\n"));
  439.  
  440.         ntStatus = STATUS_UNSUCCESSFUL;
  441.  
  442.         goto close_handle;
  443.     }
  444.  
  445.     length = mappedLength.LowPart;
  446.  
  447.  
  448.     //
  449.     // If the address is in io space, just return the address, otherwise
  450.     // go through the mapping mechanism
  451.     //
  452.  
  453.     if (inIoSpace)
  454.     {
  455.         *((PVOID *) ioBuffer) = physicalAddressBase.LowPart;
  456.     }
  457.  
  458.     else
  459.     {
  460.         //
  461.         // initialize view base that will receive the physical mapped
  462.         // address after the MapViewOfSection call.
  463.         //
  464.  
  465.         viewBase = physicalAddressBase;
  466.  
  467.  
  468.         //
  469.         // Let ZwMapViewOfSection pick an address
  470.         //
  471.  
  472.         virtualAddress = NULL;
  473.  
  474.  
  475.  
  476.         //
  477.         // Map the section
  478.         //
  479.  
  480.         ntStatus = ZwMapViewOfSection (physicalMemoryHandle,
  481.                                        (HANDLE) -1,
  482.                                        &virtualAddress,
  483.                                        0L,
  484.                                        length,
  485.                                        &viewBase,
  486.                                        &length,
  487.                                        ViewShare,
  488.                                        0,
  489.                                        PAGE_READWRITE | PAGE_NOCACHE);
  490.  
  491.         if (!NT_SUCCESS(ntStatus))
  492.         {
  493.             MapMemDebugPrint(("MapMem: ZwMapViewOfSection failed\n"));
  494.  
  495.             goto close_handle;
  496.         }
  497.  
  498.         //
  499.         // Mapping the section above rounded the physical address down to the
  500.         // nearest 64 K boundary. Now return a virtual address that sits where
  501.         // we wnat by adding in the offset from the beginning of the section.
  502.         //
  503.  
  504.  
  505.         (ULONG) virtualAddress += (ULONG)physicalAddressBase.LowPart -
  506.                                   (ULONG)viewBase.LowPart;
  507.  
  508.         *((PVOID *) ioBuffer) = virtualAddress;
  509.  
  510.     }
  511.  
  512.     ntStatus = STATUS_SUCCESS;
  513.  
  514.  
  515.  
  516. close_handle:
  517.  
  518.     ZwClose(physicalMemoryHandle);
  519.  
  520.  
  521.  
  522. done:
  523.  
  524.     MapMemDebugPrint(("\t ntStatus = %x\n"));
  525.     return ntStatus;
  526. }
  527.